function deepCopy(data, hash = new WeakMap()) {
  let newData;
  if (typeof data === "object") {
    // null
    if (data === null) {
      newData = data;
    }
    // Array
    else if (Array.isArray(data)) {
      newData = [];
      data.forEach(item => newData.push(deepCopy(item, hash)));
    }
    // Date
    else if (data instanceof Date) {
      newData = new Date(data);
    }
    // regular expression
    else if (data instanceof RegExp) {
      newData = new RegExp(data);
    } else if (data instanceof Set) {
      // 实现set数据的深拷贝
      newData = new Set();
      Array.from(data).forEach(item => newData.add(deepCopy(item, hash)));
    } else if (data instanceof Map) {
      // 实现map数据的深拷贝
      newData = new Map();
      data.forEach((value, key) => newData.set(deepCopy(key, hash), deepCopy(value, hash)));
    }
    // plain object
    else {
      // 用WeakMap的key保存原对象的引用记录, value是对应的深拷贝对象的引用
      // 例如: a:{b:{c:{d: null}}}, d=a, a 的深拷贝对象是 copy, 则 weakmap 里保存一条 a->copy 记录
      // 当递归拷贝到d, 发现d指向a，而a已经存在于weakmap，则让新d指向copy
      if (hash.has(data)) {
        newData = hash.get(data);
      } else {
        newData = {};
        hash.set(data, newData);
        for (let prop in data) {
          newData[prop] = deepCopy(data[prop], hash);
        }
      }
    }
  }
  // 基本数据类型
  else {
    newData = data;
  }
  return newData;
}

export { deepCopy };
